package com.itheima.tanhua.dubbo.handler;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Lff
 * @date 2022/2/26
 * <p>
 * 自定义的元数据处理器：
 * 用来统一操作添加或修改时的某些字段值的填充
 * <p>
 * 探花版本
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入操作自动填充
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        setNeedFillFields(metaObject, Arrays.asList(FieldFill.INSERT, FieldFill.INSERT_UPDATE));
        metaObject.setValue("updated",new Date());
        metaObject.setValue("created",new Date());
    }

    /**
     * 更新操作自动填充
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        setNeedFillFields(metaObject, Arrays.asList(FieldFill.UPDATE, FieldFill.INSERT_UPDATE));
        metaObject.setValue("updated",new Date());
    }

    /**
     * 动态的去给指定字段赋值
     *
     * @param metaObject
     * @param fills
     */
    public void setNeedFillFields(MetaObject metaObject, List<FieldFill> fills) {
        //获取当前需要设置的这个实体对象
        Object obj = metaObject.getOriginalObject();
        //获取对应的字节码文件从中获取这个类的所有属性
        Field[] fields = obj.getClass().getDeclaredFields();
        //获得这个类的所有带TableField注解的属性
        Map<String, Class> maps = Arrays.stream(fields).filter(item -> {
            TableField annotation = item.getAnnotation(TableField.class);
            //没有这个注解 排除掉
            if (annotation == null) {
                return false;
            }
            FieldFill fill = annotation.fill();
            //注解没有这个属性 排除掉
            if (fill == null) {
                return false;
            }

            //仅当属性里有这参数里的属性 就把它放到集合中
            // 遍历这些属性 选出含有value =INSERT_UPDATE INSERT UPDATE
            for (FieldFill f : fills) {
                if (fill.name().equals(f.name())) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toMap(Field::getName, Field::getType));
        //操作符合条件的属性
        maps.forEach((fName, fClass) -> {
            //获取字段的属性类型
            //进行赋值
            if (fClass == Date.class) {
                metaObject.setValue(fName, new Date());
            }else {
                 throw new RuntimeException("自动填充类型错误！！");
            }
        });
    }

}
